package com.example.apt.processor

import com.google.auto.service.AutoService
import com.google.common.collect.ImmutableSet
import com.squareup.javapoet.JavaFile
import com.zq.apt.annotation.BindView
import javax.annotation.processing.AbstractProcessor
import javax.annotation.processing.ProcessingEnvironment
import javax.annotation.processing.Processor
import javax.annotation.processing.RoundEnvironment
import javax.lang.model.SourceVersion
import javax.lang.model.element.TypeElement
import javax.lang.model.element.VariableElement
import javax.lang.model.util.Elements
import java.io.IOException


@AutoService(Processor::class)
class BindViewProcessor : AbstractProcessor() {
    private val mProxyMap: HashMap<String, ClassCreatorProxy> = HashMap()
    private var mElementUtils: Elements? = null
    override fun init(processingEnv: ProcessingEnvironment?) {
        super.init(processingEnv)
        mElementUtils = processingEnv?.elementUtils
    }

    override fun getSupportedAnnotationTypes(): MutableSet<String> {
        return mutableSetOf(BindView::class.java.canonicalName)
    }

    override fun getSupportedSourceVersion(): SourceVersion {
        return SourceVersion.latestSupported()
    }

    override fun process(set: MutableSet<out TypeElement>?, roundEnvironment: RoundEnvironment?): Boolean {
        println("BindViewProcessor:process()")
        mProxyMap.clear()
        val elements = roundEnvironment?.getElementsAnnotatedWith(BindView::class.java)
        if(elements != null){
            for(element in elements){
                val variableElement = element as VariableElement
                val classElement = variableElement.enclosingElement as TypeElement
                val fullClassName = classElement.qualifiedName.toString()
                println("BindViewProcessor:  $fullClassName ${variableElement.simpleName}")
                //elements的信息保存到mProxyMap中
                var proxy = mProxyMap[fullClassName]
                if (proxy == null) {
                    proxy = ClassCreatorProxy(mElementUtils, classElement)
                    mProxyMap[fullClassName] = proxy
                }
                val bindAnnotation = variableElement.getAnnotation(BindView::class.java)
                val id = bindAnnotation.value
                proxy.putElement(id, variableElement)
            }

            //通过javapoet生成
            for (key in mProxyMap.keys) {
                val proxyInfo = mProxyMap[key]
                val packageName = proxyInfo!!.packageName
                val typeSpec = proxyInfo.generateJavaCode()
                val javaFile: JavaFile = JavaFile.builder(packageName, typeSpec).build()
                try {
                    //　生成文件
                    val fileName = if (packageName.isEmpty()) typeSpec.name else packageName + "." + typeSpec.name
                    println("BindViewProcessor:  生成文件: $fileName")
                    javaFile.writeTo(processingEnv.filer)
                } catch (e: IOException) {
                    e.printStackTrace()
                }
            }
        }
        return false
    }
}